/**
 * @author 14544
 * @date 2020/4/17 13:55
 */
window.onload = function () {
    {
        let sourceElement = null;
        const dragEle = document.querySelector('.drag-item');
        const dropEleList = document.querySelectorAll('.dropzone');
        // 定义要拖拽容器的监听事件
        dragEle.addEventListener('drag', function (e) {
            // 在整个拖拽过程中不至触发一次
            console.log("drag 当拖拽元素、选中的文本时触发");
        })

        dragEle.addEventListener('dragstart', function (e) {
            console.log('开始拖动...')
            console.log("dragStart: dropEffect = " + e.dataTransfer.dropEffect + " ; effectAllowed = " + e.dataTransfer.effectAllowed);
            // DataTransfer.effectAllowed 属性指定拖放操作所允许的一个效果。
            // 应该在 dragstart (en-US)事件中设置此属性，，以便为【拖动源】设置所需的拖动效果，其他事件中设置将无效
            // 是为拖动源设置的，表示拖动源可以被执行那些拖动操作
            e.dataTransfer.effectAllowed = 'move';
            // 设置拖拽数据

            e.dataTransfer.setData('text/plain', e.target.parentNode.innerText)

            // 添加items数据
            var dataList = e.dataTransfer.items;
            dataList.add(e.target.id, "text/plain2");
            // Add some other items to the drag payload
            dataList.add("<p>... paragraph ...</p>", "text/html");
            dataList.add("http://www.example.org", "text/uri-list");
            console.log("dragStart: dataTransfer = ", e.dataTransfer)
            //设置拖拽反馈图像
            dragWithCustomImage(e)
            e.target.style.opacity = .5;
            sourceElement = e.target
        })

        // 完成拖拽操作，不管有没有放置到其他区域，这个方法最终都会调用
        dragEle.addEventListener('dragend', function (e) {
            console.log('完成拖拽操作...');
            sourceElement.style.opacity = 1;
        })

        // 定义放置容器的监听事件
        dropEleList.forEach(function (ele) {
            ele.addEventListener('dragenter', function (e) {
                e.stopPropagation();
                e.preventDefault();
                console.log('首次进入放置区域...')
                console.log('目标元素：')
                console.log(e.target)
                if (sourceElement && [...e.target.classList].includes('dropzone')) {
                    e.target.classList.add('active')
                }
            })
            ele.addEventListener('dragover', function (e) {
                e.stopPropagation();
                e.preventDefault();  // 阻止默认行为， 因为web中大多数元素默认是不支持drop的，所以要阻止其默认行为，才能正常drop，也可以根据dataTransfer.types 、dropEffect等属性来选择性的drop
                console.log('仍停留在放置区域...');
                // DataTransfer.dropEffect 属性控制在拖放操作中给用户的反馈（通常是视觉上的）。它会影响在拖拽过程中光标的手势。
                e.dataTransfer.dropEffect = 'move';
                console.log("dragover: dropEffect = " + e.dataTransfer.dropEffect + " ; effectAllowed = " + e.dataTransfer.effectAllowed);
            })
            ele.addEventListener('dragleave', function (e) {
                e.stopPropagation();
                e.preventDefault();
                console.log("离开放置区域...");
                if (sourceElement && [...e.target.classList].includes('dropzone')) {
                    e.target.classList.remove('active')
                }
            })
            ele.addEventListener('dragexit', function (e) {
                // 在整个拖拽过程中不至触发一次
                console.log("dragexit 当元素变得不再是拖拽操作的选中目标时触发。");
            })
            ele.addEventListener('drop', function (e) {
                e.stopPropagation();
                e.preventDefault(); // 阻止默认动作（如打开一些元素的链接）
                console.log('放下元素...')
                console.log("drop: dropEffect = " + e.dataTransfer.dropEffect + " ; effectAllowed = " + e.dataTransfer.effectAllowed);
                console.log("drop: dataTransfer = ", e.dataTransfer)
                // 如果当前的放置区域是dropzone，并且拖拽的行为是move，那么就删除掉来源元素原来所在区域，并在此区域内添加
                if (sourceElement && e.dataTransfer.effectAllowed === 'move' && [...e.target.classList].includes('dropzone')) {
                    sourceElement.parentNode.removeChild(sourceElement);
                    e.target.appendChild(sourceElement)
                }
                // 获取拖拽数据
                let sourceData = e.dataTransfer.getData('text/plain')
                sourceData += e.dataTransfer.getData('custom/plain')

                // 读取item数据
                var data = e.dataTransfer.items;
                // Loop through the dropped items and log their data
                for (var i = 0; i < data.length; i++) {
                    if ((data[i].kind == 'string') && (data[i].type.match('^text/plain3'))) {
                        // This item is the target node
                        data[i].getAsString(function (s) {
                            e.target.appendChild(document.getElementById(s));
                        });
                    } else if ((data[i].kind == 'string') && (data[i].type.match('^text/html'))) {
                        // Drag data item is HTML
                        data[i].getAsString(function (s) {
                            console.log("... Drop: HTML = " + s);
                        });
                    } else if ((data[i].kind == 'string') && (data[i].type.match('^text/uri-list'))) {
                        // Drag data item is URI
                        data[i].getAsString(function (s) {
                            console.log("... Drop: URI = " + s);
                        });
                    }
                }
                console.log(sourceData)
            })
        })
    }

    function dragWithCustomImage(event) {
        var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
        canvas.width = canvas.height = 50;
        canvas.id = 'canvas'
        var ctx = canvas.getContext("2d");
        ctx.lineWidth = 4;
        ctx.moveTo(0, 0);
        ctx.lineTo(50, 50);
        ctx.moveTo(0, 50);
        ctx.lineTo(50, 0);
        ctx.stroke();

        var dt = event.dataTransfer;
        document.body.appendChild(canvas)
        dt.setData('custom/plain', 'custom Drag img');
        // 第一个参数是对图像的引用。这个引用通常是一个图像元素，但它也可以是画布（canvas）或任何其他元素
        // 第二和第三个参数是图像应该相对于鼠标指针出现位置的偏移量。
        dt.setDragImage(canvas, 25, 25);
    }
}
